iT邦幫忙

2021 iThome 鐵人賽

DAY 18
0
自我挑戰組

邊工作邊進行前端學習之旅系列 第 18

[Day 18] JS - 變數提升Hoisting

  • 分享至 

  • xImage
  •  

前言

今天又要來介紹新的基礎觀念啦,在認識Hoisting之前,只單純知道宣告變數的方式,也沒有在乎它放在程式哪個段落會不會有影響。
在 JavaScript 中,不管你在函數中的哪一行用 var 宣告變數,一律視為在函數的第一行宣告。雖然單純看來是被移動到程式的區塊頂端,但要注意的是,變數和函數的宣告會在編譯階段就被放入記憶體,這樣做的優點,可以在程式碼宣告該函式之前使用它。

學習資源分享

  1. 彭彭 - JavaScript 網頁前端工程入門:Hoisting 宣告提升,這次一樣推薦彭彭老師的前端工程入門,講解的很慢、很清楚,對當時第一次聽的我來說,可以快速抓住要點。
  2. MDN - Hoisting,MDN 也有 Hoisting 範例說明,能夠快速理解 Hoisting 是什麼。

舉例說明:

  • var x=1之前寫上console,x印出來會是什麼? 會印出undefined
  • 完全同等var x=undefined; console.log(x); x=1;
  • 如果直接宣告console.log(y)會出現referenceError:y is not defined(因為從來都沒有直接用var 去宣告過y)

  console.log(x);
    var x = 1;
  • 完全同等
 var x = undefined
    console.log(x);
    x = 1;
  • 沒有宣告過的變數,會出現錯誤

以上範例為基本對於提升的解釋,雖然學程式的時候我們就學到了一個觀念,「程式是一行一行跑」,但因為hoisting,即便在console.log之後,才宣告var x,也會因為「提升」,而到了最上面。

那除了宣告變數會提升之外,函式呢?

  • 函式的宣告也會提升
    • 優先權比較高
 console.log(x) //[Function: x]
    var x
    function x() { }

也可參考此範例,更清楚了解函式的優先提升

  • 上述宣告變數使用var,而在 ES6 裡多了兩個宣告變數:let 及const。

let 跟 const 與 hoisting

console.log(x);// ReferenceError: x is not defined
    let x

以為這樣let就沒有提升嗎?直到看到Huli老師文章範例

var a = 10
function test(){
  console.log(a)
  let a;   //這裡也用let宣告a
}
test()

Huli:
如果 let 真的沒有 hoisting 的話,答案應該會輸出10,因為 log 那一行會存取到外面的var a = 10的這個變數
答案卻是:ReferenceError: a is not defined
意思就是,它的確提升了,只是提升後的行為跟 var 比較不一樣。

  • 與 var 的差別在於提升之後,var 宣告的變數會被初始化為 undefined,而 let 與 const 的宣告不會被初始化為 undefined。
  • 在「提升之後」以及「賦值之前」這段「期間」,如果你存取它就會拋出錯誤,而這段期間就稱做是 TDZ(Temporal Dead Zone),它是一個為了解釋 let 與 const 的 hoisting 行為所提出的一個名詞。

重複宣告

函式和變數同名,則函式會優先

同時多個函式同名

最後一個 test 會覆寫前面的宣告,因此得到 3。


    test(); // 3

    function test() {
      console.log(1);
    }

    function test() {
      console.log(2);
    }

    function test() {
      console.log(3);
    }

參考資料
我知道你懂 hoisting,可是你了解到多深?
JS 額外補充:hoisting 變數提升
你懂 JavaScript 嗎?#13 拉升(Hoisting)


上一篇
[Day 17] JS - 冒泡事件 (Event Bubbling)
下一篇
[Day 19] JS - 作用域 Scope
系列文
邊工作邊進行前端學習之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言